package com.googlecode.jbeansdb.impl;

import java.util.Arrays;

import org.apache.log4j.Logger;

public class MemcachedDecoder {
	private static final Logger log = Logger.getLogger(MemcachedDecoder.class);
	private static MemcachedDecoder decoder = new MemcachedDecoder();
	protected MemcachedDecoder() {
		
	}
	
	public static MemcachedDecoder getInstance() {
		return decoder; 
	}
	
	public String getCommandName(byte[] input) {
		return getChunk(input, 0, ' ');
	}
	
	public String getGetKey(String op, byte[] input) {
		return getChunk(input, op.length(), '\r');
	}
	
	public String getSetKey(String op, byte[] input) {
		int index = 0;
		byte prev = (byte)' ';
		byte curr = -1;
		int start = 3;
		for (int i = start; i < input.length; i++) {
			curr = input[i];
			if (curr == (byte)' ' && prev == (byte)' ') {
				start = i + 1;
			} else if (curr == (byte)' ') {
				index = i;
				break;
			}
			
			prev = curr;
		}
		
		log.debug("start: " + start + ", index: " + index);
		return new String(Arrays.copyOfRange(input, start, index)).trim();
	}
	
	public int getValueLength(byte[] input) {
		return Integer.parseInt(getChunk(input, 0, '\r', 4, ' '));
	}
	
	public String getValue(byte[] input) {
		int index = 0;
		for (int i = 0; i < input.length; i++) {
			if (input[i] == (byte)'\n') {
				index = i;
				break;
			}
		}
		
		// -2 is to exclude the \r\n
		String ret = new String(Arrays.copyOfRange(input, index, input.length - 2)).trim();
		
		log.info("input is: " + new String(input) + ", ret is: " + ret);
		return ret;
	}
	
	private String getChunk(byte[] input, int start, char endChar) {
		return getChunk(input, start, endChar, 0, ' ');
	}
	
	private String getChunk(byte[] input, int start, char endChar, int skip, char skipChar) {
		int index = 0;
		int skiped = 0;
		byte prev = -1;
		byte curr = -1;
		for (int i = start; i < input.length; i++) {
			curr = input[i];
			if (curr == (byte)' ' && ++skiped <= skip && prev != (byte)' ') {
				start = i + 1;
			} else if (curr == (byte)endChar) {
				index = i;
				break;
			}
			
			prev = curr;
		}
		
		log.debug("start: " + start + ", index: " + index);
		return new String(Arrays.copyOfRange(input, start, index)).trim();
	}
}
